#include "retangulo.h"

Retangulo::Retangulo( Vector *posicao, Vector *eixol, Vector *eixoc, double largura, double comprimento, Color *cor, double kAmbiente, double kDifusa, double kReflexao, double nShing)
: Object(cor,posicao,kAmbiente,kDifusa,kReflexao,nShing){
	this->eixoLargura = eixol->vetorUnitario();
	this->eixoComprimento = eixoc->vetorUnitario();
	this->largura = largura;
	this->comprimento = comprimento;
}

Retangulo::Retangulo( Vector *posicao, Vector *eixol, Vector *eixoc, double largura, double comprimento)
: Object(){
	this->posicao = posicao;
	this->eixoLargura = eixol->vetorUnitario();
	this->eixoComprimento = eixoc->vetorUnitario();
	this->largura = largura;
	this->comprimento = comprimento;
}

Vector* Retangulo::vetorNormal(Ray *raio){
	return this->vetorNormal();
}
/**
* retorna o vetor normal ao plano do retangulo 
*/
Vector* Retangulo::vetorNormal(){
	
	Vector* normal = this->eixoLargura->produtoVetorial(this->eixoComprimento);
	return normal->vetorUnitario();

}
/**
* testa se ha colisao do raio passado com o retangulo
*/
bool Retangulo::testarColisao(Ray *raio) {
	
	double t = 0 , vn = 0, a = 0, b = 0, b1, b2, c1, c2, c3, c4;
	Vector *p; // ponto de intercecsao com o plano do triangulo 
	Vector *po = raio->getPosicao(); // posicao inicial do raio
	Vector *v = raio->getDirecao(); // direcao do raio
	Vector *n = this->vetorNormal(); // vetor normal ao plano do triangulo 

	Vector* p1 = this->eixoLargura->multiplicacao(this->largura);  // vetores que determinam o plano (p1 , p2)
	Vector* p2 = this->eixoComprimento->multiplicacao(this->comprimento); // 
	
	vn = v->produtoEscalar(n);
	if ( vn != 0){

		Vector *aux = this->posicao->subtracao(po); // (A - Po)
		t = (aux->produtoEscalar(n)) / (vn); // (A - Po)* N / (V * N)
		p = po->soma(v->multiplicacao(t)); // P = Po + tV
		
		p = p->subtracao(this->posicao);
		
		// resolve P = a*P1 + b*P2 , encontrando a e b
		b1 = p->getCoord(0) + p->getCoord(1);
		b2 = p->getCoord(1) + p->getCoord(2);
		
		c1 = p1->getCoord(0) + p1->getCoord(1);
		c2 = p1->getCoord(1) + p1->getCoord(2);
		
		c3 = p2->getCoord(0) + p2->getCoord(1);
		c4 = p2->getCoord(1) + p2->getCoord(2);
		
		a = (b1 * c4 - b2 * c3) / (c1 * c4 - c2 * c3);
		b = (c1 * b2 - c2 * b1) / (c1 * c4 - c2 * c3);

		if ((a >= 0) && (a <= 1) && (b >= 0) && (b <= 1) ) {
			return true;
		} else {
			return false;
		} 

	} else {
		return false;
	}

}


Intersect* Retangulo::intersessao(Ray *raio){

	double t = 0 , vn = 0, a = 0, b = 0, b1, b2, c1, c2, c3, c4;
	Vector *p; // ponto de intercecsao com o plano do triangulo 
	Vector *po = raio->getPosicao(); // posicao inicial do raio
	Vector *v = raio->getDirecao(); // direcao do raio
	Vector *n = this->vetorNormal(); // vetor normal ao plano do triangulo 

	Vector* p1 = this->eixoLargura->multiplicacao(this->largura);  // vetores que determinam o plano (p1 , p2)
	Vector* p2 = this->eixoComprimento->multiplicacao(this->comprimento); // 
	Vector* p3;

	vn = v->produtoEscalar(n);
	if ( vn != 0){

		Vector *aux = this->posicao->subtracao(po); // (A - Po)
		t = (aux->produtoEscalar(n)) / (vn); // (A - Po)* N / (V * N)
		p = po->soma(v->multiplicacao(t)); // P = Po + tV
		
		p3 = p->subtracao(this->posicao);
		
		// resolve P = a*P1 + b*P2 , encontrando a e b
		b1 = p3->getCoord(0) + p3->getCoord(1);
		b2 = p3->getCoord(1) + p3->getCoord(2);
		
		c1 = p1->getCoord(0) + p1->getCoord(1);
		c2 = p1->getCoord(1) + p1->getCoord(2);
		
		c3 = p2->getCoord(0) + p2->getCoord(1);
		c4 = p2->getCoord(1) + p2->getCoord(2);
		
		a = (b1 * c4 - b2 * c3) / (c1 * c4 - c2 * c3);
		b = (c1 * b2 - c2 * b1) / (c1 * c4 - c2 * c3);

		if ((a >= 0) && (a <= 1) && (b >= 0) && (b <= 1) ) {
			return (new Intersect( p, n, t));
		} else {
			return (NULL);
		} 

	} else {
		return (NULL);
	}
}


